/**
 * Namespace for all Omplus project classes and methods.
 * @author Ompluscator, Churava, Krca, Marko
 * @type {Namespace}
 * @version 0.1
 */
var Omplus = Omplus || {};

/**
 * Defining constants
 * @type {Object}
 */
Omplus.constants = {
    init : "init",
    render : "render",
    array : "array",
    object : "object",
    string : "string",
    undefined : "undefined",
    control : "control",
    container : "container",
    desktop : "desktop",
    loader : "loader",
    validators : "validators",
    events : "events",
    omplusType : "omplusType",
    panel:"panel",
    errorsPanel:"errorsPanel",
    response_parameters : "response_parameters",
    response_errors : "errors",
    status : "status",
    status_ok : "ok",
    status_error : "error",
    status_bad_request : "bad_request"
}


/**
 * String - Object pairs that contain all the global objects
 * @type {Object}
 */
Omplus.globals = {
    objects : {},
    notCreated : {},
    forFuture : {},
    modelReferences : {},
    getForFuture : function(objectName){
        return this.forFuture[objectName];
    },
    getObject : function(objectName){
        return this.objects[objectName];
    },
    setObject : function(objectName, objectValue){
        this.objects[objectName] = objectValue;
    },
    getNotCreated : function(){
        return this.notCreated;
    },
    getNotCreatedLength : function(){
        return this.notCreatedLength;
    },
    pushNotCreated : function(className, properties){
        var type = className.prototype.omplusType.split(".");
        if (!this.notCreated[type[2]]) this.notCreated[type[2]] = [];
        this.notCreated[type[2]].push({
            className : className,
            properties: properties
        });
        this.notCreatedLength++;
    },
    notCreatedLength : 0
}

/**
 * Namespace for core classes and methods.
 * @type {Namespace}
 */
Omplus.base = {};

Omplus.models = {};

Omplus.views = {};

Omplus.controllers = {};

Omplus.events = {};

Omplus.proxy = {};

Omplus.layouts = {};

Omplus.validators = {};

Omplus.application = {};

Omplus.actions = {};

/**
 * Definition of mother of all classes
 * @constructor
 */
Omplus.base.Class = function(){};

Omplus.base.Class.prototype["omplusType"] = "Class";

/**
 * Function that creates the Instance of a class with given properties
 * @param className
 * @param properties
 * @return {*}
 */
Omplus.base.create = function(className, properties){
    if (properties["omplusType"]) delete properties.omplusType;
    var omplusClass = Omplus.base.extend(className, properties);
    var object = new omplusClass();
    if (object.omplusName) Omplus.globals.setObject(object.omplusName, object);
    return object;
};


/**
 * Function for extending classes
 * @param className
 * @param properties
 * @return {Function}
 */
Omplus.base.extend = function(className, properties){
    var object = jQuery.extend(true, {}, className.prototype);

    /**
     * Adding all new properties to parent prototype and thus extending it
     */
    for (var property in properties){
        switch (property){

            case Omplus.constants.validators:
            case Omplus.constants.events:
                if (!object[property])
                    object[property] = [];
                for(var i in properties[property])
                    object[property].push(properties[property][i]);
                break;
            case Omplus.constants.init :
            case Omplus.constants.render :
                if (!object[property + Omplus.constants.array]){
                    object[property + Omplus.constants.array] = [];
                }
                object[property + Omplus.constants.array].push(properties[property]);
                break;
            case Omplus.constants.omplusType :
                object[property] = object[property] + "." + properties[property];
                break;
            default:
                object[property] = properties[property];
                break;
        }
    }

    /**
     * Constructor
     * Adding all the functions from init array and render array to constructor
     * @
     */
    var omplusClass = function(){
        var arrays = [Omplus.constants.init, Omplus.constants.render];
        for (var functionName in arrays){
            if (object[arrays[functionName] + Omplus.constants.array]){
                /**
                 * Passing the function to object.init because "this" will point to the object then
                 */
                for (var initialize in object[arrays[functionName] + Omplus.constants.array]){
                    object.init = object[arrays[functionName] + Omplus.constants.array][initialize];
                    object.init();
                }
            }
        }
    };

    /**
     * Adding the prototype to the new class
     */
    omplusClass.prototype = object;

    return omplusClass;
};

Omplus.base.define = function(className, properties){
    Omplus.globals.pushNotCreated(className, properties);
};


/**
 * Father of all classes
 * @type {omplusClass}
 */
Omplus.base.Base = Omplus.base.extend(Omplus.base.Class,{
    init: function(){},
    omplusName : null,
    omplusType : "Base",
    isOmplus : true
});